#ifndef _DCMCTRL_H_
#define _DCMCTRL_H_

#ifdef __cplusplus
 extern "C" {
#endif

#include "stm32g4xx_hal.h"
#include "BoardConfig.h"
#include "MSP_GPIO.h"

#define USE_KFP			//如果使用KFP的话，就定义这个

/* 恒流模块的使能引脚 */
#define DCM1_EN(n)			(n?HAL_GPIO_WritePin(DCM1_EN_Port, DCM1_EN_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(DCM1_EN_Port, DCM1_EN_Pin, GPIO_PIN_RESET))
#define DCM2_EN(n)			(n?HAL_GPIO_WritePin(DCM2_EN_Port, DCM2_EN_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(DCM2_EN_Port, DCM2_EN_Pin, GPIO_PIN_RESET))
#define DCM3_EN(n)			(n?HAL_GPIO_WritePin(DCM3_EN_Port, DCM3_EN_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(DCM3_EN_Port, DCM3_EN_Pin, GPIO_PIN_RESET))
#define DCM4_EN(n)			(n?HAL_GPIO_WritePin(DCM4_EN_Port, DCM4_EN_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(DCM4_EN_Port, DCM4_EN_Pin, GPIO_PIN_RESET))
#define DCM5_EN(n)			(n?HAL_GPIO_WritePin(DCM5_EN_Port, DCM5_EN_Pin, GPIO_PIN_SET):HAL_GPIO_WritePin(DCM5_EN_Port, DCM5_EN_Pin, GPIO_PIN_RESET))


#define DCM_Vref                300      //参考电压3。3v时 就是330
#define DCM_Vref_Multi          100     //参考电压的倍数
#define DCM_DAC_Resolution      12      //DAC输出分辨率
#define DCM_DAC_MAX          	((1 << DCM_DAC_Resolution) - 1)
#define DCM_ADC_Resolution      12
#define DCM_ADC_MAX             ((1 << DCM_ADC_Resolution) - 1)

#define DCM_OUTCurr_Gain_O			    755		//旧板， 读取输出电流的比例系数：  2.65V对应的是20A   2.65 * 7.55 = 20A		

#define DCM_OUTVolt_Gain			    833		//读取输出电压的比例系数：  3.0V对应的是25V    3.0 * 8.33 = 25V  
#define DCM_Gain_Multi        			100

#define DCM_Gain_Num      			    20 

//给用户使用的校准参数 
#define ADJ_Curr_Gear_Num         11

#define DCM_ANALOGIN_Size       2  

#define DCM1_OUTCurr_Index			0
#define DCM1_OUTVolt_Index			1
#define DCM2_OUTVolt_Index			0
#define DCM2_OUTCurr_Index			1
#define DCM3_OUTCurr_Index			1
#define DCM3_OUTVolt_Index			0
#define DCM4_OUTVolt_Index			0
#define DCM4_OUTCurr_Index			1
#define DCM5_OUTCurr_Index			0
#define DCM5_OUTVolt_Index			1

//extern float DCM_OUTCurr_Max;      // 输出最大电流
//extern float DCM_OUTCurr_Min;      // 输出最小电流
//extern float DCM_OUTCurr_Limit;   // 判断有无电流的最小值

//测试用
//extern float Get_OUTCurr_Volt[DCModuleNum];
//extern float Get_SetCurr_Volt[DCModuleNum]; 

//extern uint8_t DCM_SetCurr_Now_Cnt[DCModuleNum];

/* PLC发送过来的校准参数的分段标志 */
typedef enum 
{
	ADJ_Whole_Curr 	        = 0xF0,     //1A～15A全部都一起调整
	ADJ_Curr_10             = 0xF1,     //满量程15A，10%档，即1～1.5A
    ADJ_Curr_20             = 0xF2,     //满量程15A，20%档，即1.5A～3A
    ADJ_Curr_30             = 0xF3,     //满量程15A，30%档，即3A～4.5A
    ADJ_Curr_40             = 0xF4,     //满量程15A，40%档，即4.5A～6A
    ADJ_Curr_50             = 0xF5,     //满量程15A，50%档，即6A～7.5A
    ADJ_Curr_60             = 0xF6,     //满量程15A，60%档，即7.5A～9A
    ADJ_Curr_70             = 0xF7,     //满量程15A，70%档，即9A～10.5A
    ADJ_Curr_80             = 0xF8,     //满量程15A，80%档，即10.5A～12A
    ADJ_Curr_90             = 0xF9,     //满量程15A，90%档，即12A～13.5A
    ADJ_Curr_100            = 0xFA,     //满量程15A，100%档，即13.5A～15A
} ADJ_DCM_Curr_t;

#if 0
typedef enum 
{
	ADJ_Whole_Curr 	       = 0xA0,     //1A～20A全部都一起调整
	ADJ_Curr_1             = 0xA1,     //满量程20A，1A档， 即0.8A～1.5A
    ADJ_Curr_2             = 0xA2,     //满量程20A，2A档， 即1.5A～2.5A
    ADJ_Curr_3             = 0xA3,     //满量程20A，3A档， 即2.5A～3.5A
    ADJ_Curr_4             = 0xA4,     //满量程20A，4A档， 即3.5A～4.5A
    ADJ_Curr_5             = 0xA5,     //满量程20A，5A档， 即4.5A～5.5A
    ADJ_Curr_6             = 0xA6,     //满量程20A，6A档， 即5.5A～6.5A
    ADJ_Curr_7             = 0xA7,     //满量程20A，7A档， 即6.5A～7.5A
    ADJ_Curr_8             = 0xA8,     //满量程20A，8A档， 即7.5A～8.5A
    ADJ_Curr_9             = 0xA9,     //满量程20A，9A档， 即8.5A～9.5A
    ADJ_Curr_10            = 0xAA,     //满量程20A，10A档，即9.5A～10.5A
	ADJ_Curr_11            = 0xAB,     //满量程20A，11A档，即10.5A～11.5A
	ADJ_Curr_12            = 0xAC,     //满量程20A，12A档，即11.5A～12.5A
	ADJ_Curr_13            = 0xAD,     //满量程20A，13A档，即12.5A～13.5A
	ADJ_Curr_14            = 0xAE,     //满量程20A，14A档，即13.5A～14.5A
	ADJ_Curr_15            = 0xAF,     //满量程20A，15A档，即14.5A～15.5A
	ADJ_Curr_16            = 0xB0,     //满量程20A，16A档，即15.5A～16.5A
	ADJ_Curr_17			   = 0xB1,	   //满量程20A，17A档，即16.5A～17.5A
	ADJ_Curr_18			   = 0xB2,     //满量程20A，18A档，即17.5A～18.5A
	ADJ_Curr_19			   = 0xB3,     //满量程20A，19A档，即18.5A～19.5A
	ADJ_Curr_20            = 0xB4,     //满量程20A，20A档，即19.5A～20A
} ADJ_DCM_Curr_t;
#endif

/* PLC发送过来的校准参数的标记，PLC发送过来的调整电流值时，状态的变化 */
typedef enum 
{
	DCM_Adjust_FromPLC_Save_Err        = -2,        //保存参数失败
	DCM_Adjust_FromPLC_SetData_Err     = -1,        //设置参数超过范围
    DCM_Adjust_FromPLC_Default         = 0,        //默认状态，未收到校准参数
    DCM_Adjust_FromPLC_Goto            = 1,        //正在校准，就是将PLC发送过来的数据，线保存到DCM_AdjustOUTCurr_FromPLC[]中
    DCM_Adjust_FromPLC_Doing           = 2,        //校准完成，将参数保存到FLASH中
	DCM_Adjust_FromPLC_Saved           = 3,        //校准完成，将参数保存到FLASH中
	DCM_Adjust_FromPLC_ShowTime		   = 4,
} DCM_Adjust_FromPLC_t;

//#ifdef USE_AdjustFunc
//extern DCM_Adjust_FromPLC_t DCM_Adjust_Flag[DCModuleNum];
//#endif

/* 输出电流控制信号ctrl采用分段比例放大的方式 */
typedef struct
{
	uint16_t SetCurr_Gain_1A;			//0.8A~1.5A
	uint16_t SetCurr_Gain_2A;			//1.5~2.5A
	uint16_t SetCurr_Gain_3A;			//2.5A~3.5A
	uint16_t SetCurr_Gain_4A;			//3.5A~4.5A
	uint16_t SetCurr_Gain_5A;			//4.5A~5.5A
	uint16_t SetCurr_Gain_6A;			//5.5A~6.5A
	uint16_t SetCurr_Gain_7A;			//6.5A~7.5A
	uint16_t SetCurr_Gain_8A;			//7.5A~8.5A
	uint16_t SetCurr_Gain_9A;			//8.5A~9.5A
	uint16_t SetCurr_Gain_10A;			//9.5A~10.5A
	uint16_t SetCurr_Gain_11A;			//10.5A~11.5A
	uint16_t SetCurr_Gain_12A;			//11.5A~12.5A
	uint16_t SetCurr_Gain_13A;			//12.5A~13.5A
	uint16_t SetCurr_Gain_14A;			//13.5A~14.5A
	uint16_t SetCurr_Gain_15A;			//14.5A~15.5A
	uint16_t SetCurr_Gain_16A;			//15.5A~16.5A
	uint16_t SetCurr_Gain_17A;			//16.5A~17.5A
	uint16_t SetCurr_Gain_18A;			//17.5A~18.5A
	uint16_t SetCurr_Gain_19A;			//18.5A~19.5A
	uint16_t SetCurr_Gain_20A;			//19.5A~20A
}DCM_SetCurr_Gain_Handle;

/* 输出电流反馈信号curr采用分段比例放大的方式 */
typedef struct 
{
	uint16_t OUTCurr_Gain_1A;			//0.8A~1.5A
	uint16_t OUTCurr_Gain_2A;			//1.5~2.5A
	uint16_t OUTCurr_Gain_3A;			//2.5A~3.5A
	uint16_t OUTCurr_Gain_4A;			//3.5A~4.5A
	uint16_t OUTCurr_Gain_5A;			//4.5A~5.5A
	uint16_t OUTCurr_Gain_6A;			//5.5A~6.5A
	uint16_t OUTCurr_Gain_7A;			//6.5A~7.5A
	uint16_t OUTCurr_Gain_8A;			//7.5A~8.5A
	uint16_t OUTCurr_Gain_9A;			//8.5A~9.5A
	uint16_t OUTCurr_Gain_10A;			//9.5A~10.5A
	uint16_t OUTCurr_Gain_11A;			//10.5A~11.5A
	uint16_t OUTCurr_Gain_12A;			//11.5A~12.5A
	uint16_t OUTCurr_Gain_13A;			//12.5A~13.5A
	uint16_t OUTCurr_Gain_14A;			//13.5A~14.5A
	uint16_t OUTCurr_Gain_15A;			//14.5A~15.5A
	uint16_t OUTCurr_Gain_16A;			//15.5A~16.5A
	uint16_t OUTCurr_Gain_17A;			//16.5A~17.5A
	uint16_t OUTCurr_Gain_18A;			//17.5A~18.5A
	uint16_t OUTCurr_Gain_19A;			//18.5A~19.5A
	uint16_t OUTCurr_Gain_20A;			//19.5A~20A
}DCM_OUTCurr_Gain_Handle;



typedef enum
{
	DCModule_1			= 0,
	DCModule_2		    = 1,
	DCModule_3			= 2,
	DCModule_4			= 3,
	DCModule_5 			= 4,
} DCModule_t;

#if 0
typedef enum
{
	DCMState_Work		   		= 10201,		//工作
	DCMState_Stop				= 10401,		//停止

	DCMState_Adjust_Doing		= 10501,		//正在调整电流值
	DCMState_Adjust_Done		= 10502,		//调整电流值完成，
	DCMState_Adjust_Saved		= 10503,		//已保存到FLASH中

	DCMState_OUT_OverCurr		= 30101,		//输出电流过大，报此错误: 30101~30105
	DCMState_IN_NoVolt			= 30201,		//是否有输入电压，没有输入电压，报此错误: 30201~30205
	DCMState_OUT_Break			= 30301,		//输出断路，报此错误: 30301~30305
	DCMState_Fault				= 30401,		//模块故障，报此错误: 30401~30405
//	DCMState_OUT_Short			= 30501,		//输出短路，报此错误: 30501~30505
	DCMState_OverTemp			= 30601,		//模块温度过高
	//DCMState_OUT_Energy			= 30701,		//输出能量异常
	DCMState_OUT_UnderVolt		= 30801,		//输出电压过低
	DCMState_OUT_OverVolt		= 30901,		//输出电压过大

	DCMState_Set_OutCurr_Err	= 40101,		//设置输出电流值错误 超过20A，或者小于0.8A
	DCMState_Set_AdjustCurr_Err = 40201,		//设置调整电流值错误 超过150%，或者小于50%
} DCModule_State_t;
#endif


typedef enum
{
	Disable_DCM	= 0,
	Enable_DCM  = 1,	
} DCModuleENOUT_t;

enum
{
	DCM_Normal	= 0,
	DCM_Fault  = 1,	
};

enum
{
	DCM_Have_INVolt  = 0,	
	DCM_No_INVolt	 = 1,
};


#if 0
typedef struct
{
	uint8_t EXTIPinCnt[DCModuleNum];
	uint8_t PinDebounde[DCModuleNum];
	uint8_t PinValue[DCModuleNum];
	uint32_t TrigLastTime[DCModuleNum];
}
EXTIPINHandler_t;

EXTIPINHandler_t DCM_Fault_h;
EXTIPINHandler_t DCM_Pdet_h;
#endif


//读取每个模块的输出电流和输出电压，保存在buffer中
typedef struct
{
    uint16_t        DCM1_ANALOGIN[DCM_ANALOGIN_Size];            //保存第一个模块的ADC输入 [Volt, Curr]
    uint16_t        DCM2_ANALOGIN[DCM_ANALOGIN_Size];            //保存第一个模块的ADC输入 [Volt, Curr]
    uint16_t        DCM3_ANALOGIN[DCM_ANALOGIN_Size];            //保存第一个模块的ADC输入 [Curr, Volt]
    uint16_t        DCM4_ANALOGIN[DCM_ANALOGIN_Size];            //保存第一个模块的ADC输入 [Volt, Curr]
    uint16_t        DCM5_ANALOGIN[DCM_ANALOGIN_Size];            //保存第一个模块的ADC输入 [Curr, Volt]
}DCModule_AnalogIn_t;//对象的句柄

uint8_t ADC_CONV_COMPLETE_FLAG;

//DCM恒流模块 执行控制指令时，需要用到的参数
typedef struct
{
	uint8_t DCM_No;
	uint8_t DCM_EnablePin;
	float DCM_SetCurr_V;
}DCModule_OUTCtrl_t;

//卡尔曼滤波
typedef struct
{
    float LastP;//上次估算协方差 初始化值为0.02
    float Now_P;//当前估算协方差 初始化值为1
	float Last_out;//上次卡尔曼滤波器输出 初始化值为0
    float out;//卡尔曼滤波器输出 初始化值为0
    float Kg;//卡尔曼增益 初始化值为0
    float Q;//过程噪声协方差 初始化值为0.0001
    float R;//观测噪声协方差 初始化值为5
}KFP;//Kalman Filter parameter


void dcm_init(void);
void dcm_save_outcurrpara(uint8_t ch, float set_outcurr, uint8_t adjust_gear);
void open_dcm_outcurr(uint8_t ch);
void close_dcm_outcurr(uint8_t ch);
uint8_t dcm_enable_output(uint8_t ch, uint8_t en);
uint8_t dcm_read_enable_value(uint8_t ch);
uint8_t dcm_set_outcurrent(uint8_t ch, float value);
float dcm_get_setcurr_volt(uint8_t ch);
void dcm_save_setoutcurr_now(uint8_t ch, float curr);

void dcm_start_adjust_process(uint8_t ch, uint8_t gear_i, uint8_t adjust_gear);
void dcm_end_adjust_process(uint8_t ch);
//uint8_t dcm_set_adjustcurr(uint8_t ch, uint8_t value);
uint8_t dcm_get_adjustcurrgear(uint8_t ch);

float dcm_get_outcurrent(uint8_t ch);
uint8_t dcm_get_currisoutofset_num(uint8_t ch);
float dcm_get_outcurr_volt(uint8_t ch);
float dcm_get_outvoltage(uint8_t ch);
float dcm_get_real_outputcurr(uint8_t ch);
DCModule_State_t dcm_get_dcmstate(uint8_t ch);
#ifdef USE_AdjustFunc
void dcm_write_adjustflag(uint8_t ch, DCM_Adjust_FromPLC_t dcmadj);
#endif
uint8_t dcm_get_dcmfault(uint8_t ch);
uint8_t dcm_read_fault_value(uint8_t ch);
uint8_t dcm_get_pdet(uint8_t ch);
uint8_t dcm_read_pdet_value(uint8_t ch);

void start_analogout(uint8_t ch);
void stop_analogout(uint8_t ch);
void set_analogout(uint8_t ch, uint32_t value);
void start_analogin(uint8_t ch);
void stop_analogin(uint8_t ch);

uint8_t dcm_saved_data_toFLASH(uint32_t startaddr, uint32_t len, uint8_t *data);
void dcm_read_data_fromFLASH(void);

//float kalmanFilter(float ADC_Value);
float kalmanFilter(KFP *kfp, float input);
KFP* KFP_DCM_Curr_Index(uint8_t ch);

uint8_t Get_AdjCurrGear_NO(float curr);
uint8_t Get_AdjustCurr(uint8_t ch);
char *DCModule_State_Log(DCModule_State_t dcmstate);

void Error_Handler(void);

#ifdef __cplusplus
}
#endif

#endif  /* _DCMCTRL_H_ */
